package com.xyz.service.impl;

import cn.hutool.core.date.DateUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.xyz.entity.mapper.MessageInfoMapper;
import com.xyz.entity.pojo.MessageInfo;
import com.xyz.entity.pojo.MessageInfoExample;
import com.xyz.entity.pojo.SystemRole;
import com.xyz.service.MessageService;
import com.xyz.util.dto.DataResult;
import com.xyz.util.dto.GridData;
import com.xyz.util.dto.LoginInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Service
@Transactional(rollbackFor = Exception.class)
public class MessageServiceImpl implements MessageService {

    private static final Logger logger = LoggerFactory.getLogger(MessageServiceImpl.class);

    public static final Map<String, SseEmitter> sseEmitterMap = new ConcurrentHashMap<>();
    static long seeMessageIndex = 0L;

    @Autowired
    MessageInfoMapper messageInfoMapper;

    @Override
    public SseEmitter connect(String token) {
        SseEmitter sseEmitter = new SseEmitter(600 * 1000L);
        // 连接成功需要返回数据，否则会出现待处理状态
        try {
            sseEmitter.send(SseEmitter.event().comment("SSE连接成功"));
        } catch (IOException e) {
            logger.error("SSE连接失败");
            return sseEmitter;
        }
        // 连接断开
        sseEmitter.onCompletion(() -> {
            sseEmitterMap.remove(token);
        });
        // 连接超时
        sseEmitter.onTimeout(() -> {
            sseEmitterMap.remove(token);
        });
        // 连接报错
        sseEmitter.onError((throwable) -> {
            sseEmitterMap.remove(token);
        });
        sseEmitterMap.put(token, sseEmitter);
        return sseEmitter;
    }

    @Override
    public void sendMessage(Map<String, Map<String, Object>> map) {
        sseEmitterMap.forEach((token, sseEmitter) -> {
            if (map.containsKey(token)) {
                Map<String, Object> dataMap = map.get(token);
                try {
                    dataMap.put("index", seeMessageIndex);
                    sseEmitter.send(dataMap, MediaType.APPLICATION_JSON);
                    seeMessageIndex++;
                } catch (IOException e) {
                    logger.error("SSE发送数据失败：" + e);
                }
            }
        });
    }

    @Override
    public DataResult selectMessage(LoginInfo li, int pageNum, int pageSize, int messageType) throws Exception {
        MessageInfoExample miExample = new MessageInfoExample();
        miExample.createCriteria().andUserIdEqualTo(li.getLoginUserId()).andMessageTypeEqualTo(messageType);
        miExample.setOrderByClause("create_time desc");
        Page<MessageInfo> page = PageHelper.startPage(pageNum, pageSize);
        List<MessageInfo> miList = messageInfoMapper.selectByExample(miExample);
        List<Map<String, Object>> list = new ArrayList<>();
        for (MessageInfo mi : miList) {
            Map<String, Object> map = new HashMap<>();
            map.put("id", mi.getId());
            map.put("title", mi.getTitle());
            map.put("content", mi.getContent());
            map.put("state", mi.getState());
            map.put("businessType", mi.getBusinessType());
            map.put("businessId", mi.getBusinessId());
            map.put("businessCode", mi.getBusinessCode());
            map.put("time", DateUtil.formatDateTime(mi.getCreateTime()));
            list.add(map);
        }
        return DataResult.build9100(new GridData(page.getTotal(), list));
    }

    @Override
    public DataResult updateMessageState(LoginInfo li, long id) throws Exception {
        MessageInfo newMi = new MessageInfo();
        newMi.setState(2);
        if (id <= 0) {
            MessageInfoExample miExample = new MessageInfoExample();
            miExample.createCriteria().andUserIdEqualTo(li.getLoginUserId());
            messageInfoMapper.updateByExampleSelective(newMi, miExample);
        } else {
            newMi.setId(id);
            messageInfoMapper.updateByPrimaryKeySelective(newMi);
        }
        return DataResult.build9100();
    }

}
